/**
 * @file ha_device.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2024-01-10
 *
 * @copyright Copyright (c) 2024
 *
*/
#include "FreeRTOS.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ha_mqtt.h"
#include "cJSON.h"
#include "log.h"

#define DBG_TAG "ha_device"
static char* payload[1024];

extern unsigned char mac[];
/**
 * @brief 创建实体，并向HomeAssistant 发送发现信息
 *
 * @param client
 * @param discovery_topic
 * @param discovery_payload
*/
void homeAssistant_create_device(aiio_mqtt_client_handle_t client, discovery_payload_t* discovery_payload_handle, const char* entity_type, const char* s_name)
{
    if (client==NULL) {
        LOG_E("MQTT client is null,client is not init");
        return;
    }

    char* mqtt_discovery_topic = aiio_os_malloc(256);
    discovery_payload_t* discovery_payload = discovery_payload_handle;

    discovery_payload->name = s_name;
    discovery_payload->sw_version = "1.0.0";

    discovery_payload->device.identifiers_len = 1;
    discovery_payload->device.identifiers[0] = homeAssistant_dev.dev_mac;
    discovery_payload->device.name = homeAssistant_dev.dev_name;
    discovery_payload->device.manufacturer = "Ai-Thinker";
    discovery_payload->device.model = CONFIG_DEVICE_TYPE;
    discovery_payload->device.sw_version = discovery_payload->sw_version;
    if (discovery_payload->unique_id ==NULL) {
        discovery_payload->unique_id = aiio_os_malloc(64);
        memset(discovery_payload->unique_id, 0, 64);
        sprintf(discovery_payload->unique_id, "%s_%02x%02x", discovery_payload->name, mac[4], mac[5]);
    }

    if (discovery_payload->command_topic==NULL) {
        discovery_payload->command_topic = aiio_os_malloc(256);
        memset(discovery_payload->command_topic, 0, 256);
        sprintf(discovery_payload->command_topic, "%s/%s/%s/%s/set", HA_AUTOMATIC_DISCOVERY, entity_type, homeAssistant_dev.dev_mac, discovery_payload->unique_id);
    }
    if (discovery_payload->state_topic==NULL) {
        discovery_payload->state_topic = aiio_os_malloc(256);
        memset(discovery_payload->state_topic, 0, 256);
        sprintf(discovery_payload->state_topic, "%s/%s/%s/%s/state", HA_AUTOMATIC_DISCOVERY, entity_type, homeAssistant_dev.dev_mac, discovery_payload->unique_id);
    }

    if (discovery_payload->name==NULL
        ||discovery_payload->sw_version==NULL
        ||discovery_payload->unique_id==NULL
        ||discovery_payload->device.identifiers_len==0
        ||discovery_payload->device.name==NULL) {
        LOG_E("HomeAssistant param errpr");
        return;
    }
    cJSON* root = cJSON_CreateObject();
    if (root==NULL) {
        LOG_E("cjson root Create error");
        return;
    }
    cJSON_AddStringToObject(root, "name", discovery_payload->name);
    cJSON_AddStringToObject(root, "command_topic", discovery_payload->command_topic);
    cJSON_AddStringToObject(root, "state_topic", discovery_payload->state_topic);
    cJSON_AddStringToObject(root, "unique_id", discovery_payload->unique_id);
    cJSON* device = cJSON_CreateObject();
    cJSON* identifiers_arr = cJSON_AddArrayToObject(device, "identifiers");
    for (size_t i = 0; i < discovery_payload->device.identifiers_len; i++)
    {
        cJSON_AddItemToArray(identifiers_arr, cJSON_CreateString(discovery_payload->device.identifiers[i]));
    }
    cJSON_AddStringToObject(device, "name", discovery_payload->device.name);
    //添加产商名称
    if (discovery_payload->device.manufacturer!=NULL) cJSON_AddStringToObject(device, "manufacturer", discovery_payload->device.manufacturer);
    //添加设备型号
    if (discovery_payload->device.model!=NULL) cJSON_AddStringToObject(device, "model", discovery_payload->device.model);
    //添加设备软件版本
    if (discovery_payload->device.sw_version!=NULL) cJSON_AddStringToObject(device, "sw_version", discovery_payload->device.sw_version);
    cJSON_AddStringToObject(root, "availability_topic", discovery_payload->availability_topic);
    cJSON_AddStringToObject(root, "payload_available", "online");
    cJSON_AddStringToObject(root, "payload_not_available", "offline");
    cJSON_AddItemToObject(root, "device", device);
    char* json_data = cJSON_PrintUnformatted(root);

    memset(mqtt_discovery_topic, 0, 256);
    sprintf(mqtt_discovery_topic, "%s/%s/%s/config", HA_AUTOMATIC_DISCOVERY, entity_type, s_name);

    int msg_id = aiio_mqtt_client_publish(client, mqtt_discovery_topic, json_data, strlen(json_data), 0, 0);
    if (msg_id>0) {
        LOG_E("mqtt publish error,topic=%s,payload=%s", mqtt_discovery_topic, json_data);
    }
    else {
        LOG_D("mqtt publish success\r\ntopic=%s,\r\npayload=%s", mqtt_discovery_topic, json_data);
    }
    msg_id = aiio_mqtt_client_subscribe(client, discovery_payload->command_topic, 0);

    //发送在线消息
    vPortFree(json_data);
    cJSON_Delete(root);
    vPortFree(mqtt_discovery_topic);
}
/**
 * @brief 发送状态，可向HomeAssistant 开关状态
 *
 * @param client
 * @param discovery_payload
 * @param state
*/
void homeAssistant_send_state(aiio_mqtt_client_handle_t client, discovery_payload_t* discovery_payload, int state)
{
    if (client==NULL|| discovery_payload->state_topic==NULL) {
        LOG_E("MQTT client is null,client is not init");
        return;
    }

    int msg_id = aiio_mqtt_client_publish(client, discovery_payload->state_topic, state?"ON":"OFF", state?2:3, 0, 0);
}
/**
 * @brief 解析出事件
 *
 * @param discovery_payload
 * @param topic
 * @param topic_len
 * @param payload
 * @param payload_len
 * @return ha_event_t
*/
ha_event_t homeassistant_get_event(discovery_payload_t* discovery_payload, const char* topic, int topic_len, const char* payload, int payload_len)
{

    if (discovery_payload==NULL||topic==NULL||payload==NULL) {
        LOG_E("params is error");
        return HOMEASSISTANT_EVENT_ERR;
    }
    ha_event_t ha_event = HOMEASSISTANT_EVENT_NONE;
    char* mqtt_discovery_topic = aiio_os_malloc(256);
    char* tp = aiio_os_malloc(256);
    char* pl = aiio_os_malloc(256);
    memset(tp, 0, 256);
    memset(pl, 0, 256);
    strncpy(tp, topic, topic_len);
    strncpy(pl, payload, payload_len);

    memset(mqtt_discovery_topic, 0, 256);
    sprintf(mqtt_discovery_topic, "%s/status", HA_AUTOMATIC_DISCOVERY);
    if (!strncmp(tp, mqtt_discovery_topic, topic_len))
    {
        if (!strcmp(pl, "online"))
            ha_event = HOMEASSISTANT_EVENT_ONLINE;
        else if (!strcmp(pl, "offline")) ha_event = HOMEASSISTANT_EVENT_OFFLINE;
    }
    else {
        while (strcmp(tp, discovery_payload->command_topic)!=0) discovery_payload++;
        if (strcmp(discovery_payload->name, "relay1")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_RELY1_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_RELY1_OFF;
        }
        else if (strcmp(discovery_payload->name, "relay2")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_RELY2_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_RELY2_OFF;
        }
        else if (strcmp(discovery_payload->name, "relay3")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_RELY3_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_RELY3_OFF;
        }
        else if (strcmp(discovery_payload->name, "relayall")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_RELY_ALL_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_RELY_ALL_OFF;
        }
        else if (strcmp(discovery_payload->name, "mod_work")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_WORK;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_OFF;
        }
        else if (strcmp(discovery_payload->name, "mod_outhome")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_OUTHOME;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_OFF;
        }
        else if (strcmp(discovery_payload->name, "mod_sleep")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_SLEEP;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_OFF;
        }
        else if (strcmp(discovery_payload->name, "mod_vidio")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_VIDIO;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_OFF;
        }
        else if (strcmp(discovery_payload->name, "xiaomiSW")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_XIAOMISW_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_XIAOMISW_OFF;
        }
        else if (strcmp(discovery_payload->name, "HomeKitSW")==0) {
            if (!strcmp(pl, "ON"))ha_event = HOMEASSISTANT_EVENT_MOD_HOMEKITSW_ON;
            else if (!strcmp(pl, "OFF"))ha_event = HOMEASSISTANT_EVENT_MOD_HOMEKITSW_OFF;
        }
    }

    aiio_os_free(mqtt_discovery_topic);
    aiio_os_free(tp);
    aiio_os_free(pl);

    return ha_event;
}
/**
 * @brief 发送状态 主要是是在线和离线状态
 *
 * @param discovery_payload
 * @param status "online"or "offline"
*/
void homeassistant_send_status(char* status)
{
    if (fd_client==NULL||status == NULL) {
        LOG_E("Client is NULL");
        return;
    }
    if (strcmp(status, "online")!=0 && strcmp(status, "offline")!=0) {
        LOG_E("status is =%s,not's online or offline");
        return;
    }
    aiio_mqtt_client_publish(fd_client, discovery_payload[0].availability_topic, status, strlen(status), 0, 1);
}


void homeassistant_send_mode(ha_event_t ha_event)
{
    if (fd_client==NULL) {
        LOG_E("Client is NULL");
        return;
    }
    switch (ha_event)
    {
        case HOMEASSISTANT_EVENT_MOD_OUTHOME:
        {

            homeAssistant_send_state(fd_client, &discovery_payload[4], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[5], 1);
            homeAssistant_send_state(fd_client, &discovery_payload[6], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[7], 0);
        }
        break;
        case HOMEASSISTANT_EVENT_MOD_WORK:
        {
            homeAssistant_send_state(fd_client, &discovery_payload[4], 1);
            homeAssistant_send_state(fd_client, &discovery_payload[5], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[6], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[7], 0);
        }
        break;
        case HOMEASSISTANT_EVENT_MOD_SLEEP:
        {
            homeAssistant_send_state(fd_client, &discovery_payload[4], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[5], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[6], 1);
            homeAssistant_send_state(fd_client, &discovery_payload[7], 0);
        }
        break;
        case HOMEASSISTANT_EVENT_MOD_VIDIO:
        {
            homeAssistant_send_state(fd_client, &discovery_payload[4], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[5], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[6], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[7], 1);
        }
        break;
        case HOMEASSISTANT_EVENT_MOD_OFF:
        {
            homeAssistant_send_state(fd_client, &discovery_payload[4], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[5], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[6], 0);
            homeAssistant_send_state(fd_client, &discovery_payload[7], 0);
        }
        break;

    }
}